package application;

import gui.GUIWindow;

import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileLock;
import java.util.concurrent.Semaphore;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import parameters.RlmServerParameters;
import server.RLM_Server;
import utils.ConsoleRedirect;
import utils.NICManager;
import actions.ExitAction;


public class Application implements ApplicationInterface {

	private static GUIWindow window = null;
	
	private File lockFile = null;
	private FileLock lock = null;
	
	private RLM_Server rlmServerReference = null;
		
	public static Semaphore startSemaphore = new Semaphore(1, true);

	
	private Application() {
		
		ShutdownHook hook = new ShutdownHook(this);
		Runtime.getRuntime().addShutdownHook(hook);
		
		// not in use in test version
		if ( acquireLock() == false ) {
			alreadyRun();
			System.exit(1);
		}

        try {
			startSemaphore.acquire();
		}
        catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		ConsoleRedirect.redirectToDefault();
		
		RlmServerParameters.loadParameters();
		
		NICManager.readAdapters();
		
		RlmServerParameters.printParameters();
		
		window = new GUIWindow(this);
		window.setVisible(true);
	}
	
	

	/**
	 * This methos creates RLM folder in user home folder and stores lock file object.
	 * @return - true if lock acquired, otherwise false
	 */
	private boolean acquireLock() {
		String userDir = System.getProperty("user.dir");
		
		String rlmDir = userDir + "/" + "lock";
		
		File rlmDirFile = new File(rlmDir);
		
		if ( !rlmDirFile.exists() ) {
			rlmDirFile.mkdir();
		}
		
		lockFile = new File(rlmDirFile, "Lock.dat");
		
		
		try {
			lock = new FileOutputStream( lockFile ).getChannel().tryLock();
			
			if ( lock == null ) {
				return false;
			}
		}
		catch (IOException ioe) {
			ioe.printStackTrace();
		}
		
		return true;
		
	}

	
	/**
	 * This method releases acquired lock.
	 */
	private void releaseLock() {
		try {
			if (lock != null)
				lock.release();
		}
		catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
	
	
	
	private void alreadyRun() {
		JOptionPane.showMessageDialog(null, "RLM Server instance already started !", "Warning!", JOptionPane.WARNING_MESSAGE);
	}
	
	
	
	// shutdown hook mechanism
	
	public void freeResources() {
		try {
			releaseLock();
		}
		catch (Exception ee) {
			ee.printStackTrace();
		}
	}


	protected void finalize() throws Throwable {
		try {
			freeResources();
		}
		finally {
			super.finalize();
		}
	}
	
	
	
	/**
	 * This is the EXIT method of RLM Application.
	 */
	public static void exitRLMApplication() {
		ActionEvent exitEvent = new ActionEvent(Application.class, 0, "exit_app");
		if (window != null) {
			window.getActionManager().getExitAction().actionPerformed(exitEvent);
		}
		else {
			ExitAction exitAction = new ExitAction(null);
			exitAction.actionPerformed(exitEvent);
		}
	}
	
	
	public RLM_Server getRlmServerReference() {
		return rlmServerReference;
	}


	public void setRlmServerReference(RLM_Server processReference) {
		this.rlmServerReference = processReference;
	}
	
	
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				new Application();
			}
		});
	}
	
}
